home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / disk / misc / FitDisk2_1.lha / FitDisk.c next >
Encoding:
C/C++ Source or Header  |  1994-02-08  |  11.1 KB  |  401 lines

  1. /* FitDisk V2.0
  2.    Christian Stieber, Konradstraße 41, D-85055 Ingolstadt (Germany)
  3.    stieber@informatik.tu-muenchen.de */
  4.  
  5. /* This program is PUBLIC DOMAIN */
  6.  
  7. /* Note: this program assumes that SAS/C does not access local
  8.    variables via SP, but instead loads SP into an adress register
  9.    at function entry, and uses that register to access the local
  10.    variables (link / unlink) !!!!
  11.    This is required to make the stack-switching work
  12. */
  13.  
  14. /* define V39 if you want to compile for V39 and above ONLY */
  15. /* #define V39 */
  16.  
  17. #define STACK_SIZE 4096
  18.  
  19. #ifndef EXEC_EXECBASE_H
  20. #include <exec/execbase.h>
  21. #endif
  22.  
  23. #ifndef DOS_DOSEXTENS_H
  24. #include <dos/dosextens.h>
  25. #endif
  26.  
  27. #ifndef PROTO_EXEC_H
  28. #include <proto/exec.h>
  29. #endif
  30.  
  31. #ifndef PROTO_DOS_H
  32. #include <proto/dos.h>
  33. #endif
  34.  
  35. #ifndef V39
  36. #ifndef CLIB_ALIB_PROTOS_H
  37. APTR LibAllocPooled( APTR poolHeader, unsigned long memSize );
  38. APTR LibCreatePool( unsigned long memFlags, unsigned long puddleSize,
  39.     unsigned long threshSize );
  40. void LibDeletePool( APTR poolHeader );
  41. void LibFreePooled( APTR poolHeader, APTR memory, unsigned long memSize );
  42. #endif   /* CLIB_ALIB_PROTOS_H */
  43. #else /* V39 only */
  44. #define LibAllocPooled AllocPooled
  45. #define LibCreatePool CreatePool
  46. #define LibDeletePool DeletePool
  47. #define LibFreePooled FreePooled
  48. #endif   /* V39 */
  49.  
  50. #include <string.h>
  51.  
  52. /***********************************************/
  53.  
  54. struct FileInfo   /* This structure holds information about a file */
  55.    {
  56.       struct FileInfo *Next;
  57.       long Blocks;
  58.       char Name[1];
  59.    };
  60.  
  61. struct Arguments   /* Filled in by ReadArgs() */
  62.    {
  63.       long *BlocksFree;
  64.       char *Directory;
  65.       long OFS;
  66.       long MSDOS;
  67.    };
  68.  
  69. /***********************************************/
  70.  
  71. struct ExecBase *SysBase;
  72. struct DosLibrary *DOSBase;
  73.  
  74. static struct Arguments Arguments=
  75.    {
  76.       NULL,
  77.       NULL,
  78.       FALSE,
  79.       FALSE
  80.    };
  81.  
  82. static long BlocksFree=1756;   /* the default number of free blocks */
  83.  
  84. static void *MemoryPool;       /* heap */
  85.  
  86. static long Files=0;                     /* number of files in list */
  87. static struct FileInfo *FileList=NULL;   /* the directory */
  88.  
  89. static struct FileInfo ***Selected;      /* complicated... which files are selected at each level of the recursion */
  90.  
  91. static long Break=RETURN_OK;             /* set if we have to break */
  92.  
  93. static struct StackSwapStruct *Stacks;   /* an array of stacks for the recursion */
  94.  
  95. static char Version[]="$VER: FitDisk 2.1 (26.01.94)"
  96. #ifdef V39
  97. " (V39)"
  98. #endif
  99. ;
  100.  
  101. /***********************************************/
  102.  
  103. static void MakeFileList(void);
  104. static int ReadDir(void);
  105.  
  106. /***********************************************/
  107.  
  108. int __saveds main(void)
  109.  
  110. {
  111.    int RC;
  112.    struct RDArgs *RDArgs;
  113.  
  114.    RC=RETURN_OK;
  115.    SysBase=*(struct ExecBase **)4;
  116.    if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37))
  117.       {
  118.          if (MemoryPool=LibCreatePool(0,64*1024,64*1024))
  119.             {
  120.                if (RDArgs=ReadArgs("BLOCKS/N,DIRECTORY=DIR,OFS/S,MSDOS/S",(long *)&Arguments,NULL))
  121.                   {
  122.                      if (Arguments.BlocksFree)
  123.                         {
  124.                            BlocksFree=*Arguments.BlocksFree;
  125.                         }
  126.                      else if (Arguments.MSDOS)
  127.                         {
  128.                            BlocksFree=1426;
  129.                         }
  130.                      if (!(RC=ReadDir()) && Files)
  131.                         {
  132.                            if (Selected=LibAllocPooled(MemoryPool,(Files+1)*sizeof(struct FileInfo **)))
  133.                               {
  134.                                  memset(Selected,0,(Files+1)*sizeof(struct FileInfo **));
  135.                                  if (Stacks=LibAllocPooled(MemoryPool,Files*sizeof(struct StackSwapStruct)))
  136.                                     {
  137.                                        memset(Stacks,0,Files*sizeof(struct StackSwapStruct));
  138.                                        MakeFileList();
  139.                                        RC=Break;
  140.                                     }
  141.                                  else
  142.                                     {
  143.                                        PrintFault(IoErr(),NULL);
  144.                                        RC=RETURN_ERROR;
  145.                                     }
  146.                               }
  147.                            else
  148.                               {
  149.                                  PrintFault(IoErr(),NULL);
  150.                                  RC=RETURN_ERROR;
  151.                               }
  152.                         }
  153.                      FreeArgs(RDArgs);
  154.                   }
  155.                else
  156.                   {
  157.                      PrintFault(IoErr(),NULL);
  158.                      RC=RETURN_ERROR;
  159.                   }
  160.                LibDeletePool(MemoryPool);
  161.             }
  162.          else
  163.             {
  164.                PrintFault(IoErr(),NULL);
  165.                RC=RETURN_ERROR;
  166.             }
  167.          CloseLibrary((struct Library *)DOSBase);
  168.       }
  169.    else
  170.       {
  171.          RC=100;
  172.       }
  173.    return RC;
  174. }
  175.  
  176. /***********************************************/
  177.  
  178. static BOOL MakeSelected(int k)
  179.  
  180. {
  181.    if ((Selected[k]) ||
  182.        (Selected[k]=LibAllocPooled(MemoryPool,(k+2)*sizeof(struct FileInfo *))))
  183.       {
  184.          memset(Selected[k],0,(k+2)*sizeof(struct FileInfo *));
  185.          return TRUE;
  186.       }
  187.    else
  188.       {
  189.          PrintFault(IoErr(),NULL);
  190.          Break=RETURN_ERROR;
  191.          return FALSE;
  192.       }
  193. }
  194.  
  195. /***********************************************/
  196.  
  197. static BOOL MakeStack(int k)
  198.  
  199. {
  200.    if ((Stacks[k].stk_Lower) ||
  201.        (Stacks[k].stk_Lower=LibAllocPooled(MemoryPool,STACK_SIZE)))
  202.       {
  203.          Stacks[k].stk_Upper=((ULONG)(Stacks[k].stk_Lower))+STACK_SIZE;
  204.          Stacks[k].stk_Pointer=(APTR)(Stacks[k].stk_Upper);
  205.       }
  206.    else
  207.       {
  208.          PrintFault(IoErr(),NULL);
  209.          Break=RETURN_ERROR;
  210.          return FALSE;
  211.       }
  212. }
  213.  
  214. /***********************************************/
  215.  
  216. #define MySelected     Selected[k]
  217. #define ParentSelected Selected[k+1]
  218.  
  219. static long Select_k_Files(int k, struct FileInfo *StartFile, long BlocksFree, int *FileCount)
  220.  
  221. {
  222.    long MinBlocksFree;
  223.    struct FileInfo *FirstFile;
  224.    long t;
  225.    int MyFileCount;
  226.  
  227.    MinBlocksFree=BlocksFree;
  228.    *FileCount=0;
  229.  
  230.    ParentSelected[0]=(struct FileInfo *)NULL;
  231.    if (k>=0)
  232.       {
  233.          FirstFile=StartFile;
  234.          while (FirstFile && !Break)
  235.             {
  236.                t=BlocksFree-FirstFile->Blocks;
  237.                if (t>=0)
  238.                   {
  239.                      MySelected[0]=FirstFile;
  240.                      MyFileCount=0;
  241.                      if (t)
  242.                         {
  243.                            MySelected++;
  244.                            StackSwap(&Stacks[k]);
  245.                            t=Select_k_Files(k-1,FirstFile->Next,t,&MyFileCount);
  246.                            StackSwap(&Stacks[k]);
  247.                            MySelected--;
  248.                         }
  249.                      if (t<MinBlocksFree)
  250.                         {
  251.                            MinBlocksFree=t;
  252.                            memcpy(ParentSelected,MySelected,(k+1)*sizeof(struct FileInfo *));
  253.                            *FileCount=MyFileCount+1;
  254.                            if (*FileCount==k+1) t=0;
  255.                         }
  256.                   }
  257.                if (t)
  258.                   {
  259.                      FirstFile=FirstFile->Next;
  260.                   }
  261.                else
  262.                   {
  263.                      FirstFile=NULL;
  264.                   }
  265.                if (CheckSignal(SIGBREAKF_CTRL_C))
  266.                   {
  267.                      PrintFault(ERROR_BREAK,NULL);
  268.                      Break=RETURN_WARN;
  269.                   }
  270.             }
  271.       }
  272.    return MinBlocksFree;
  273. }
  274.  
  275. /***********************************************/
  276.  
  277. static void MakeFileList(void)                                    
  278.  
  279. {
  280.    int k;
  281.    long MinBlocksFree, t;
  282.    int i;
  283.    int FileCount;
  284.  
  285.    MinBlocksFree=BlocksFree;
  286.    for (k=0; k<Files && MinBlocksFree && !Break; k++)
  287.       {
  288.          if (MakeSelected(k) && MakeSelected(k+1) && MakeStack(k))
  289.             {
  290.                t=Select_k_Files(k,FileList,BlocksFree,&FileCount);
  291.                if (!Break)
  292.                   {
  293.                      if (t<MinBlocksFree)
  294.                         {
  295.                            MinBlocksFree=t;
  296.                            Printf("I was able to fill %ld blocks with %ld file%s:\n",BlocksFree-MinBlocksFree,FileCount,FileCount==1 ? "" : "s");
  297.                            for (i=0; i<Files && Selected[k+1][i]; i++)
  298.                               {
  299.                                  Printf("%s (%ld blocks)\n",Selected[k+1][i]->Name,Selected[k+1][i]->Blocks);
  300.                               }
  301.                            PutStr("\n");
  302.                         }
  303.                   }
  304.             }
  305.       }
  306. }
  307.  
  308. /***********************************************/
  309.  
  310. static long BlocksUsed(long ByteSize)
  311.  
  312. {
  313.    if (Arguments.MSDOS)
  314.       {
  315.          return 2*((ByteSize+1023)/1024);
  316.       }
  317.    else
  318.       {
  319.          long DataBlocks;
  320.  
  321.          DataBlocks=Arguments.OFS ? (ByteSize+487)/488 : (ByteSize+511)/512;
  322.          if (!DataBlocks) DataBlocks=1;
  323.          return(DataBlocks+(DataBlocks+71)/72);
  324.       }
  325. }
  326.  
  327. /***********************************************/
  328.  
  329. static void InsertFile(struct FileInfo *FileInfo)
  330.  
  331. {
  332.    struct FileInfo *PrevInfo, *CurrentInfo;
  333.  
  334.    CurrentInfo=FileList;
  335.    PrevInfo=(struct FileInfo *)&FileList;
  336.    while (CurrentInfo && CurrentInfo->Blocks>FileInfo->Blocks)
  337.       {
  338.          PrevInfo=CurrentInfo;
  339.          CurrentInfo=CurrentInfo->Next;
  340.       }
  341.    PrevInfo->Next=FileInfo;
  342.    FileInfo->Next=CurrentInfo;
  343. }
  344.  
  345. /***********************************************/
  346.  
  347. static int ReadDir(void)
  348.  
  349. {
  350.    static struct FileInfoBlock __aligned FileInfoBlock;
  351.    struct FileInfo *FileInfo;
  352.    BPTR Directory;
  353.  
  354.    if (Arguments.Directory)
  355.       {
  356.          Directory=Lock(Arguments.Directory,ACCESS_READ);
  357.       }
  358.    else
  359.       {
  360.          Directory=DupLock(((struct Process *)(SysBase->ThisTask))->pr_CurrentDir);
  361.       }
  362.    if (Directory)
  363.       {
  364.          if (Examine(Directory,&FileInfoBlock))
  365.             {
  366.                while (ExNext(Directory,&FileInfoBlock))
  367.                   {
  368.                      if (FileInfoBlock.fib_DirEntryType<0 && BlocksUsed(FileInfoBlock.fib_Size)<=BlocksFree)
  369.                         {
  370.                            if (FileInfo=LibAllocPooled(MemoryPool,sizeof(struct FileInfo)+strlen(FileInfoBlock.fib_FileName)))
  371.                               {
  372.                                  strcpy(FileInfo->Name,FileInfoBlock.fib_FileName);
  373.                                  FileInfo->Blocks=BlocksUsed(FileInfoBlock.fib_Size);
  374.                                  InsertFile(FileInfo);
  375.                                  Files++;
  376.                               }
  377.                            else
  378.                               {
  379.                                  PrintFault(IoErr(),NULL);
  380.                                  return RETURN_ERROR;
  381.                               }
  382.                         }
  383.                   }
  384.                if (IoErr()!=ERROR_NO_MORE_ENTRIES)
  385.                   {
  386.                      goto DirError;
  387.                   }
  388.             }
  389.          else
  390.             {
  391.                goto DirError;
  392.             }
  393.       }
  394.    else
  395.       {
  396. DirError:PrintFault(IoErr(),Arguments.Directory);
  397.          return RETURN_ERROR;
  398.       }
  399.    return RETURN_OK;
  400. }
  401.